/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.lang.util;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class ClassTools {

	//private static final Log log = Logs.get();

	/**
	 * 从输入流中读取Class的名字,输入流必须是Class文件格式
	 */
	public static String getClassName(InputStream in) {
		try {
			DataInputStream dis = new DataInputStream(new BufferedInputStream(
					in));
			Map<Integer, String> strs = new HashMap<Integer, String>();
			Map<Integer, Integer> classes = new HashMap<Integer, Integer>();
			dis.skipBytes(4);// Magic
			dis.skipBytes(2);// 副版本号
			dis.skipBytes(2);// 主版本号

			// 读取常量池
			int constant_pool_count = dis.readUnsignedShort();
			for (int i = 0; i < (constant_pool_count - 1); i++) {
				byte flag = dis.readByte();
				switch (flag) {
				case 7:// CONSTANT_Class:
					int index = dis.readUnsignedShort();
					classes.put(i + 1, index);
					break;
				case 9:// CONSTANT_Fieldref:
				case 10:// CONSTANT_Methodref:
				case 11:// CONSTANT_InterfaceMethodref:
					dis.skipBytes(2);
					dis.skipBytes(2);
					break;
				case 8:// CONSTANT_String:
					dis.skipBytes(2);
					break;
				case 3:// CONSTANT_Integer:
				case 4:// CONSTANT_Float:
					dis.skipBytes(4);
					break;
				case 5:// CONSTANT_Long:
				case 6:// CONSTANT_Double:
					dis.skipBytes(8);
					i++;// 必须跳过一个,这是class文件设计的一个缺陷,历史遗留问题
					break;
				case 12:// CONSTANT_NameAndType:
					dis.skipBytes(2);
					dis.skipBytes(2);
					break;
				case 1:// CONSTANT_Utf8:
					int len = dis.readUnsignedShort();
					byte[] data = new byte[len];
					dis.readFully(data);
					strs.put(i + 1, new String(data, "UTF-8"));// 必然是UTF8的
					break;
				case 15:// CONSTANT_MethodHandle:
					dis.skipBytes(1);
					dis.skipBytes(2);
					break;
				case 16:// CONSTANT_MethodType:
					dis.skipBytes(2);
					break;
				case 18:// CONSTANT_InvokeDynamic:
					dis.skipBytes(2);
					dis.skipBytes(2);
					break;
				default:
					throw new RuntimeException("Impossible!! flag=" + flag);
				}
			}

			dis.skipBytes(2);// 版本控制符
			int pos = dis.readUnsignedShort();
			String name = strs.get(classes.get(pos));
			if (name != null)
				name = name.replace('/', '.');
			dis.close();
			return name;
		} catch (Throwable e) {
			//if (log.isInfoEnabled())
			//	log.info("Fail to read ClassName from class InputStream", e);
		}
		return null;
	}

	private static ClassLoader gClassLoader;
	static {
		gClassLoader = ClassTools.class.getClassLoader();
		// 当使用JavaSE是,如果easyplatform通过bootClassLoader加载,那么就会为null
		if (gClassLoader == null)
			try {
				gClassLoader = ClassLoader.getSystemClassLoader();
			} catch (Throwable e) {
			}
	}

	/**
	 * 获取easyplatform.jar的ClassLoader的方法
	 */
	public static ClassLoader getClassLoader() {
		return gClassLoader;
	}
}
